const {MIME_TYPE_EPUB, UPLOAD_URL, UPLOAD_PATH, OLD_UPLOAD_URL} = require('../utils/constant')
const fs = require('fs')
// const path = require('path')
const xml2js = require('xml2js').parseString
const Epub = require('../utils/epub')

class Book {
  constructor(file, data) {
    if (file) {
      this.createBookFromFile(file)
    } else if (data) {
      this.createBookFromData(data)
    }
  }

  createBookFromFile(file){
    // console.log('createBookFromFile',file);
    const {
      destination,
      filename,
      mimetype = MIME_TYPE_EPUB,
      path,
      originalname
    } = file
    const suffix = mimetype === MIME_TYPE_EPUB ? '.epub' : ''
    const oldBookPath = path
    const bookPath = `${destination}/${filename}${suffix}`
    const url = `${UPLOAD_URL}/book/${filename}${suffix}`
    const unzipPath = `${UPLOAD_PATH}/unzip/${filename}`
    const unzipUrl = `${UPLOAD_URL}/unzip/${filename}`
    if(!fs.existsSync(unzipPath)) {
      fs.mkdirSync(unzipPath, { recursive: true})
    }
    // 重命名
    if(fs.existsSync(oldBookPath) && !fs.existsSync(bookPath)){
      fs.renameSync(oldBookPath, bookPath)
    }
    this.fileName = filename //文件名
    this.path = `/book/${filename}${suffix}` 
    this.filePath = `/book/${filename}${suffix}`//epub文件相对路径
    this.url = url // epub文件下载链接
    this.title = '' 
    this.author = ''
    this.publisher = ''
    this.contents = [] //目录
    this.cover = '' //封面图图片URL
    this.category = -1 //分类ID
    this.unzipUrl = unzipUrl //解压后文件夹链接
    this.unzipPath = `/unzip/${filename}`
    this.originalname = originalname //电子书文件的原名
  }

  createBookFromData(data){
    this.contents = data.contents
    this.fileName = data.fileName
    this.cover = data.coverPath
    this.title = data.title
    this.author = data.author
    this.publisher = data.publisher
    this.bookId = data.fileName
    this.language = data.language
    this.rootFile = data.rootFile
    this.originalName = data.originalname
    this.path = data.path || data.filePath
    this.filePath = data.path || data.filePath
    this.unzipPath = data.unzipPath
    this.coverPath = data.coverPath
    this.createUser = data.username
    this.createDt = new Date().getTime()
    this.updateType = data.updateType === 0 ? data.updateType :1
    this.category = data.category || 99
    this.categoryText = data.categoryText || '自定义'
  }

  parse() {
    return new Promise( (resolve, reject) => {
      const bookPath = `${UPLOAD_PATH}${this.filePath}` //电子书路径
      if(!fs.existsSync(bookPath)) {
        reject(new Error('电子书不存在'))
      }
      const epub = new Epub(bookPath)
      epub.on('error', err => {
        reject(err)
      })
      epub.on('end',err => {
        if(err){
          reject(err)
        } else {
          // console.log(epub.metadata);
          let {
            title,
            language,
            creator,
            creatorFileAs,
            publisher,
            cover
          } = epub.metadata
          if (!title) {
            reject(new Error('图书标题为空'))
          } else {
            this.title = title
            this.language = language || 'en'
            this.author = creator || creatorFileAs || 'unknown'
            this.publisher = publisher || 'unknown'
            this.rootFile = epub.rootFile
            try {
              this.unzip()
              this.parseContents(epub).then(({chapters, chapterTree}) =>{
                this.contents = chapters
                this.contentsTree = chapterTree
                cover = cover || (epub.manifest && epub.manifest['CoverPic'] && 'CoverPic')
                if(cover === ''){
                  cover = Object.keys(this.mainfest).find( key => {
                    this.mainfest[key].properties === 'cover-image'
                  })
                } 
                if(cover === ''){
                  reject(new Error("找不到封面"))
                }
                epub.getImage(cover, handleGetImage)

              })
            } catch(e) {
              reject(e)
            }

            //getImage的回调函数
            const handleGetImage = (error, imgBuffer, mimeType) => {
              if (error) {
                reject(error)
              } else {
                // console.log(imgBuffer,mimeType);
                const suffix = mimeType.split('/')[1]
                const coverPath = `${UPLOAD_PATH}/img/${this.fileName}.${suffix}`
                const coverUrl = `${UPLOAD_URL}/img/${this.fileName}.${suffix}`
                fs.writeFileSync(coverPath, imgBuffer, 'binary')
                this.coverPath = `/img/${this.fileName}.${suffix}`
                this.cover = coverUrl
                resolve(this)
              }
            }

            // console.log(epub.manifest);
            //封面id

            
            

          }
        }
      })

      
      epub.parse()
      

    })

  }

  // findParent(array, level = 0, pid = '') {
  //   return array.map(item => {
  //     item.level = level
  //     item.pid = pid
  //     if (item.navPoint && item.navPoint.length) {
  //       item.navPoint = findParent(item.navPoint, level + 1, item['$'].id)
  //     } else if (item.navPoint) {
  //       item.navPoint.level = level + 1
  //       item.navPoint.pid = item['$'].id
  //     }
  //     return item
  //   })
  // }
  
  parseContents(epub) {

        /**
     * flatten方法，将目录转为一维数组
     *
     * @param array
     * @returns {*[]}
     */
    //只扁平化了3层目录
    function flatten(array) {
      return [].concat(...array.map(item => {
        if (item.navPoint && item.navPoint.length) {
          return [].concat(item, ...flatten(item.navPoint))
        } else if (item.navPoint) {
          return [].concat(item, item.navPoint)
        } else {
          return item
        }
      }))
    }

    /**
     * 查询当前目录的父级目录及规定层次
     *
     * @param array
     * @param level
     * @param pid
     */
    function findParent(array, level = 0, pid = '') {
      return array.map(item => {
        item.level = level
        item.pid = pid
        if (item.navPoint && item.navPoint.length) {
          item.navPoint = findParent(item.navPoint, level + 1, item['$'].id)
        } else if (item.navPoint) {
          item.navPoint.level = level + 1
          item.navPoint.pid = item['$'].id
        }
        return item
      })
    }

    function getNcxFilePath() {
      const manifest = epub && epub.manifest
      const spine = epub && epub.spine
      const ncx = manifest && manifest.ncx
      const toc = spine && spine.toc
      // console.log(ncx);
      // console.log(toc);
      const end =(ncx && ncx.href) || (toc && toc.href)
      // console.log(end);
      return end
    }
    const ncfFilePath = Book.genPath(`${this.unzipPath}/${ getNcxFilePath()}`)
    // console.log(ncfFilePath);
    const xml = fs.readFileSync(ncfFilePath,'utf-8')
    if(fs.existsSync(ncfFilePath)){
      const fileName = this.fileName
      return new Promise((resolve, reject) => {
        
        // console.log(xml); xml2js is not a function
        xml2js(xml, {
          explicitArray: false, // 设置为false时，解析结果不会包裹array
          ignoreAttrs: false  // 解析属性
        }, function(err, json) {
          if(err) {
            reject(err)
          }
          else {
            const navMap = json.ncx.navMap // 获取ncx的navMap属性
            // console.log(JSON.stringify(navMap) );
            if(navMap.navPoint && navMap.navPoint.length > 0) {
              navMap.navPoint = findParent(navMap.navPoint)
              const newNavMap = flatten(navMap.navPoint)
              const chapters = []
              epub.flow.forEach((chapter, index) => {
                if(index +1 > newNavMap.length) {
                  return
                }
                const nav = newNavMap[index]
                chapter.href = `${fileName}/${chapter.href}`
                chapter.text = `${UPLOAD_URL}/unzip/${chapter.href}`
                // console.log( chapter.text);
                if(nav && nav.navLabel){
                  chapter.label = nav.navLabel.text || ''

                } else{
                  chapter.label = ''
                }
                // const src = nav['$'].id.src
                chapter.id = `${chapter.href}`
                chapter.level = nav.level
                chapter.pid = nav.pid
                chapter.navId = nav['$'].id
                chapter.fileName = fileName
                chapter.order = index +1
                chapters.push(chapter)
                
              })
              // console.log(chapters);
              const chapterTree = []
              chapters.forEach(c => {
                c.children = []
                if(c.pid === '') {
                  chapterTree.push(c)
                } else {
                  const parent = chapters.find( _ => _.navId === c.pid)
                  parent.children.push(c)
                }
              })
              resolve({chapters, chapterTree}) 
            } else {
              reject(new Error('目录解析失败，目录数为0'))
            }
          }
         })
      })
    } else {
      throw new Error('目录文件不存在')
    }
    // return ncfFilePath

  }


  unzip() {
    const AdmZip = require('adm-zip')
    // console.log(this.unzipPath);
    // console.log(this.path);
    // if(!fs.existsSync(Book.genPath(this.unzipPath))) {
    //   fs.mkdirSync(Book.genPath(this.unzipPath), { recursive: true})
    // }
    const zip = new AdmZip(Book.genPath(this.path)) // 解析文件路径

    zip.extractAllTo(
      /*target path*/Book.genPath(this.unzipPath),
      /*overwrite*/true
    )
  }

  static genPath(path) {
    if (path.startsWith('/')) {
      // console.log(`${UPLOAD_PATH}${path}`);
      return `${UPLOAD_PATH}${path}`
    } else {
      return `${UPLOAD_PATH}/${path}`
    }
  }

  static pathExists(path){
    if(path.startsWith(UPLOAD_PATH)) {
      return fs.existsSync(path)
    } else {
      return fs.existsSync(Book.genPath(path))
    }
  }

  static genCoverUrl(book) {
    const{cover} = book
    if(book.updateType === '0') {
      if(cover){
        if(cover.startsWith('/')) {
          return `${OLD_UPLOAD_URL}${cover}`
        } else {
          return `${OLD_UPLOAD_URL}/${cover}`
        }
      }
    } else {
      if (cover) {
        if(cover.startsWith('/')) {
          return `${UPLOAD_URL}${cover}`
        } else {
          return `${UPLOAD_URL}/${cover}`
        }
      } 
    } 
    return null
  }

  static genContentsTree(chapters) {
    if(!chapters) {
      return null
    }
    const chapterTree = []
    chapters.forEach(c => {
      c.children = []
      if(c.pid === '') {
        chapterTree.push(c)
      } else {
        const parent = chapters.find( _ => _.navId === c.pid)
        parent.children.push(c)
      }
    })
    return chapterTree
  }

  toDb(){
    return {
      fileName :this.fileName,
      cover :this.coverPath,
      title : this.title,
      author : this.author,
      publisher : this.publisher,
      bookId : this.bookId,
      language : this.language,
      rootFile : this.rootFile,
      originalName : this.originalName,
      filePath : this.filePath,
      unzipPath : this.unzipPath,
      coverPath : this.coverPath,
      createUser : this.createUser,
      createDt : this.createDt,
      updateType : this.updateType,
      category : this.category ,
      categoryText : this.categoryText
    }
  }

  reset() {
    console.log(this.fileName);
    if(Book.pathExists(this.filePath)) {
      fs.unlinkSync(Book.genPath(this.filePath))
      console.log('删除文件');
    }
    if(Book.pathExists(this.coverPath)) {
      fs.unlinkSync(Book.genPath(this.coverPath))
      console.log('删除封面。。。');
    }
    if(Book.pathExists(this.unzipPath)){
      fs.rmdirSync(Book.genPath(this.unzipPath), {
        recursive: true
      })
      console.log('删除解压目录');
    }
  }

  

  getContents() {
    return this.contents;
  }

}

module.exports = Book